package cn.rengy.util.servlet;

import cn.rengy.util.ExceptionPrintUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StreamUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
public class ServletUtil {

	/**
	 * 完整URL
	 * @param request
	 * @return
	 */
	public static String getRequestURL(HttpServletRequest request){
		String param=request.getQueryString();
        StringBuilder requestUrl = new StringBuilder(request.getRequestURL());
        if (param!= null) {
            requestUrl.append("?").append(param);
        }
        return requestUrl.toString();
	}

	public static Map<String,String> getAllHeader(HttpServletRequest request){
		Map<String,String> header=new HashMap<String,String>();
		Enumeration<String> headerNames=request.getHeaderNames();
		while(headerNames.hasMoreElements()) {
			String name=headerNames.nextElement();
			String value=request.getHeader(name);
			header.put(name,value);
		}
		return header;
	}

	public static Map<String,String> getParameter(HttpServletRequest request){
		Map<String,String> parameter=new HashMap<String,String>();
		Enumeration<String> eh = request.getParameterNames();
		while (eh.hasMoreElements()){
			String parName = eh.nextElement();
			String parValue = request.getParameter(parName);
			parameter.put(parName, parValue);
		}
		return parameter;
	}


	
//	public static String getNewUrl(HttpServletRequest request) throws URISyntaxException {
//		URIBuilder b=new URIBuilder(url);
//		List<NameValuePair> nameValueList =new ArrayList<NameValuePair>();
//		nameValueList.add(new BasicNameValuePair("a",));
//		nameValueList.add(new BasicNameValuePair("b",));
//		return b.addParameters(nameValueList).build().toString();
//	}
	
	public static HttpServletRequest getHttpServletRequest(){
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request=servletRequestAttributes.getRequest();
		return request;
	}

	public static void setAttribute(String name,Object object){
		RequestAttributes attributes =  RequestContextHolder.getRequestAttributes();
		attributes.setAttribute(name,object,0);
	}

	static final String  principalKey="principal";
	public static void setPrincipal(Principal principal){
		RequestAttributes attributes =  RequestContextHolder.getRequestAttributes();
		if(attributes==null){
			throw new RuntimeException("servlet不能为空");
		}
		if(principal!=null){
			attributes.setAttribute(principalKey,principal,0);
		}
	}

	public static Principal getPrincipal(){
		RequestAttributes attributes =  RequestContextHolder.getRequestAttributes();
		if(attributes!=null){
			return (Principal)attributes.getAttribute(principalKey,0);
		}
		return null;
	}


	/**
	 * URI 不包含 http:://host:port/
	 * @param request
	 * @return
	 */
	public static String getRequestURI(HttpServletRequest request) {
		String param=request.getQueryString();
        StringBuilder requestUrl = new StringBuilder(request.getRequestURI());
        if (param!= null) {
            requestUrl.append("?").append(param);
        }
        return requestUrl.toString();
    }
	/**
	 * 只适用于nginx代理之后的
	 * @param request
	 * @return
	 */
	public static String getClientIp(HttpServletRequest request){
		//格式就是client1, proxy1, proxy2
		 String ip=request.getHeader("x-forwarded-for");
		 if(StringUtils.isNotBlank(ip)){
			 ip=ip.split(",")[0];
		 }else {
			 ip = request.getRemoteAddr();
		 }
		 return ip;
	}
	public static String getUserAgent(HttpServletRequest request){
		 return request.getHeader(HttpHeaders.USER_AGENT);
	}
	


	public static String getRequestBody(HttpServletRequest request){
		String body= null;
		if(!isUploadRequest(request)&&isAjaxRequest(request)){
			if (request.getAttribute("payload") != null) {
				// 已经读出则返回attribute中的body
				return (String)request.getAttribute("payload");
			}else{
				try {
					body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
					if(body!=null){
						body.trim();
					}
					request.setAttribute("payload",body);
				} catch (Exception e) {
					log.error(ExceptionPrintUtils.getTrace(e));
				}
			}
		}
		return body;
	}
	/**
	 * 是否返回json
	 * @param request
	 * @return
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		//||"XMLHttpRequest".equals(request.getHeader("X-Requested-With"))
		//websocket请求 也认为是ajax Upgrade: websocket  Connection: Upgrade 
		return include(MediaType.APPLICATION_JSON,request.getHeader(HttpHeaders.CONTENT_TYPE))
				||"XMLHttpRequest".equals(request.getHeader("X-Requested-With"))
				||("websocket".equals(request.getHeader(HttpHeaders.UPGRADE))
						&&HttpHeaders.UPGRADE.equals(request.getHeader(HttpHeaders.CONNECTION)) )
				||include(MediaType.APPLICATION_JSON,request.getHeader(HttpHeaders.ACCEPT))
		;
    }

	/**
	 * 是否是上传文件request
	 * @param request
	 * @return
	 */
	public static boolean isUploadRequest(HttpServletRequest request){
		return include(MediaType.MULTIPART_FORM_DATA,request.getHeader(HttpHeaders.CONTENT_TYPE));
	}

	public static void main(String[] args) {
		 System.out.println(MediaType.APPLICATION_JSON.getType());
		 System.out.println(MediaType.APPLICATION_JSON.getSubtype());
		 System.out.println(include(MediaType.APPLICATION_JSON,"application/json, text/javascript, */*; q=0.01"));
		System.out.println(include(MediaType.MULTIPART_FORM_DATA,"multipart/form-data; boundary=----WebKitFormBoundaryOxcKB58AJcHs7g6Y"));
	}
	private static boolean include(MediaType mediaType,String mediaTypes) {
		if(mediaTypes==null) {
			return false;
		}
		List<MediaType> list=MediaType.parseMediaTypes(mediaTypes);
		if(list!=null) {
			for(MediaType m:list) {
				if(mediaType.equalsTypeAndSubtype(m)){
					return true;
				}
			}
		}
		return false;
	}
	
	
	public static void responseWrite(String outStr,HttpServletResponse response) {
		try (PrintWriter printWriter = response.getWriter()) {
			printWriter.write(outStr);
			printWriter.flush();
			response.flushBuffer();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
    }
	public static void responseJson(String outStr,HttpServletResponse response) {
		response.setCharacterEncoding(StandardCharsets.UTF_8.name());
		response.setContentType(MediaType.APPLICATION_JSON_VALUE);
		try (PrintWriter printWriter = response.getWriter()) {
			printWriter.write(outStr);
			printWriter.flush();
			response.flushBuffer();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}
}
